package study.activiti.h_parallelGateway;

import java.io.InputStream;
import java.util.List;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;

/**  
 * @Name: ParallelGatewayTest
 * @Description: 并行网关测试类
 * 并行网关的特点：
 * 		1）一个流程中流程实例只有1个，执行对象有多个
 * 		2）并行网关的功能是基于进入和外出的顺序流的
 * 			分支(fork)： 并行后的所有外出顺序流，为每个顺序流都创建一个并发分支；
 * 			汇聚(join)： 所有到达并行网关，在此等待的进入分支， 直到所有进入顺序流的分支都到达以后， 流程就会通过汇聚网关。
 * 		3）并行网关的进入和外出都是使用相同节点标识
 * 		4）如果同一个并行网关有多个进入和多个外出顺序流， 它就同时具有分支和汇聚功能。 这时，网关会先汇聚所有进入的顺序流，然后再切分成多个并行分支。
 * 		5）并行网关不会解析条件。 即使顺序流中定义了条件，也会被忽略。
 * 		6）并行网关不需要是“平衡的”（比如， 对应并行网关的进入和外出节点数目不一定相等）。
 * @Author: 李超
 * @Create Date: 2016-12-14
 */
public class ParallelGatewayTest {
	
	//实例化流程引擎
	ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine() ;
	
	/**  
	* @Name: delpoymentProcessDefinition_inputStream（方法的名称）
	* @Description: 部署流程定义文件（输入流加载资源文件）（方法的描述）
	* 输入流加载资源文件的三种方式
	* 		1、从classpath跟目录下加载指定名称的文件，不加斜杠
	* 		  InputStream in = this.getClass().getClassLoader().getResourceAsStream("test.bpmn") ;
	* 		2、从当前包下加载指定名称的文件
	* 		  InputStream in = this.getClass().getResourceAsStream("test.bpmn") ;
	* 		3、从classpath跟目录下加载指定名称的文件，加斜杠
	* 		  this.getClass().getResourceAsStream("/test.bpmn") ;
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-11 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	@Test
	public void delpoymentProcessDefinition_inputStream() {
		//获取资源文件输入流
		InputStream inputStreamBpmn = this.getClass().getResourceAsStream("parallelGateway.bpmn") ;
		InputStream inputStreamPng = this.getClass().getResourceAsStream("parallelGateway.png") ;
		//部署流程定义文件
		Deployment deployment = processEngine.getRepositoryService()
					 .createDeployment()
					 .name("并行网关")
					 .addInputStream("parallelGateway.bpmn", inputStreamBpmn)
					 .addInputStream("parallelGateway.png", inputStreamPng)
					 .deploy() ;
		System.out.println("完成部署");
		System.out.println("部署id:" + deployment.getId());
		System.out.println("部署名称:" + deployment.getName());
		System.out.println("部署时间:" + deployment.getDeploymentTime());
	}
	
	/**  
	* @Name: startProcessDefinition（方法的名称）
	* @Description: 启动流程定义（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-14 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	@Test
	public void startProcessInstance() {
		//流程定义的key
		String processDefinitionKey = "parallelGateway" ;
		//根据流程定义的key启动流程实例
		ProcessInstance processInstance = processEngine.getRuntimeService()
					 .startProcessInstanceByKey(processDefinitionKey) ;
		System.out.println("流程实例启动成功");
		System.out.println("流程实例id:" + processInstance.getId());
	}
	
	/**  
	* @Name: queryParallelTask（方法的名称）
	* @Description: 根据流程实例id，查询并行网关下并发执行的任务（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-14 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	@Test
	public void queryParallelTask() {
		//流程实例id
		String processInstanceId = "125001" ;
		//根据流程实例id查询并行执行的任务
		List<Task> list = processEngine.getTaskService()
					 .createTaskQuery()
					 .processInstanceId(processInstanceId)
					 .orderByTaskCreateTime().asc()
					 .list() ;
		if(list != null && list.size() > 0) {
			for (Task task : list) {
				System.out.println("流程实例id:" + task.getProcessInstanceId());
				System.out.println("执行对象id:" + task.getExecutionId());
				System.out.println("任务名称:" + task.getName());
				System.out.println("任务办理人:" + task.getAssignee());
				System.out.println("任务创建时间:" + task.getCreateTime());
				System.out.println("#######################################");
			} 
		}
	}
	
	/**  
	* @Name: queryMyPersonalTask（方法的名称）
	* @Description: 查询指定任务办理人的个人任务（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-14 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	@Test
	public void queryMyPersonalTask() {
		//任务办理人
		String assignee = "" ;
		//查询办理人待办理的任务
		List<Task> list = processEngine.getTaskService()
					 .createTaskQuery()
					 .taskAssignee(assignee)
					 .list() ;
		if(list != null && list.size() > 0) {
			for (Task task : list) {
				System.out.println("流程实例id:" + task.getProcessInstanceId());
				System.out.println("执行对象id:" + task.getExecutionId());
				System.out.println("任务名称:" + task.getName());
				System.out.println("任务办理人:" + task.getAssignee());
				System.out.println("任务创建时间:" + task.getCreateTime());
				System.out.println("#######################################");
			}
		}
	}
	
	/**  
	* @Name: completeMyPersonalTask（方法的名称）
	* @Description: 办理个人任务，由于存在排他网关，因此在办理任务时需指定流程变量，以决定流程下一步走哪一条连线（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-14 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	@Test
	public void completeMyPersonalTask() {
		//任务id
		String taskId = "130002" ;
		//根据任务id办理个人任务
		processEngine.getTaskService().complete(taskId) ;
		System.out.println("办理成功!");
	}

}
